params provides dynamic route parameters (e.g., /products/[id]), while searchParams provides URL query string values. Both can be used in Server Components, but searchParams opts the page into dynamic rendering.
In Next.js page components, params and searchParams serve distinct purposes. params contains the dynamic route parameters defined by folder names in square brackets (like [slug]), while searchParams contains the URL's query string parameters (the part after ? in the URL). Both are available as props to page components in the App Router, and crucially, both can be used in Server Components—but with an important caveat: using searchParams opts the page into dynamic rendering at request time because query strings cannot be known at build time [citation:2][citation:6].
Source: params comes from the URL path structure defined by folder names in square brackets [citation:4]; searchParams comes from the URL query string after the ? [citation:2].
Type structure: params has a fixed shape based on your route structure (e.g., { slug: string } for [slug] routes, or { slug: string[] } for catch-all [...slug] routes) [citation:2][citation:4]; searchParams is a flexible object where keys can be strings, arrays (for repeated parameters), or undefined [citation:2][citation:6].
Rendering impact: params alone does not affect rendering mode—pages can be statically generated with known params values via generateStaticParams [citation:4]; searchParams is a Dynamic API that forces the page to use dynamic rendering because query strings cannot be known at build time [citation:2][citation:6][citation:9].
Availability: Both are available only in page components (the leaf of the route tree). Layouts do not receive searchParams to prevent stale values during navigation [citation:3][citation:5].
Yes, both params and searchParams can be used in Server Components—specifically in page components, which are Server Components by default [citation:2]. However, there are important distinctions. params is perfectly compatible with static generation: you can use generateStaticParams to pre-render pages for all known parameter combinations at build time [citation:4]. For example, an e-commerce site can pre-render all product pages by generating params for each product ID. searchParams, in contrast, forces dynamic rendering because its values cannot be known until request time—they depend on how the user interacts with the page [citation:2][citation:6][citation:9]. This trade-off is intentional: Next.js optimizes for static generation by default but gives you access to dynamic data when needed.
A significant change in Next.js 15 is that both params and searchParams are now Promises that must be awaited [citation:2][citation:9]. This change enables advanced patterns like streaming and partial rendering. In practice, this means you must use async/await or React's use() function to access the values. The official documentation emphasizes this breaking change: in version 14 and earlier, these props were synchronous, but in version 15, they are Promises (with a codemod available for migration) [citation:2]. This applies to both Server Components (using await) and Client Components (using React's use hook) [citation:2][citation:8].
Layouts and searchParams: Layouts do not receive searchParams as a prop. This is intentional—layouts are not re-rendered during navigation, so they would show stale query parameters [citation:3]. If a layout needs search params, you must read them in the page and pass them down, or use useSearchParams() in a Client Component [citation:3][citation:5].
Prop drilling challenge: For deeply nested Server Components, params and searchParams must be passed explicitly through props. There is no built-in way for arbitrary Server Components to access these values directly [citation:5][citation:7]. This has led to community solutions like @sodefa/next-server-context that use AsyncLocalStorage to share context [citation:7].
Type safety: You can use the globally available PageProps helper to get strongly typed params and searchParams from a route literal, e.g., PageProps<'/blog/[slug]'> [citation:2][citation:9].
Multiple values: If the same query parameter appears multiple times (e.g., ?tag=react&tag=nextjs), searchParams will represent it as an array: { tag: ['react', 'nextjs'] } [citation:2][citation:6].
For Client Components, Next.js provides the useSearchParams hook as an alternative to receiving searchParams as a prop [citation:3]. However, this hook has an important behavior: if used without a Suspense boundary in a statically rendered page, it will cause the component tree up to the nearest Suspense boundary to be client-side rendered, preserving the static shell while the dynamic part hydrates on the client [citation:3][citation:8]. The Next.js documentation strongly recommends wrapping components that use useSearchParams in a Suspense boundary to avoid fully client-side rendering [citation:8]. This pattern gives you the best of both worlds: a static shell with dynamic client-side hydration for the interactive parts that depend on query parameters.
You have a page at /products/[id] and the URL is /products/42?ref=google. How would you read the product id and the ref query value inside the component?
If you try to access searchParams in a pure client component, what will happen and why?
Explain what value you would expect in the params prop versus the searchParams prop for the route /blog/[slug]?draft=true.
You added a filter using searchParams to a product list page, but the list isn’t updating when the query changes. Walk me through how you’d debug the problem.
When building a Server Component that needs both the category id from the path and a page number from the query string, how would you structure the data fetching and why?
Describe a scenario where mixing params and searchParams in the same Server Component could cause unnecessary re‑renders or data fetching.
Design a pagination component that works with dynamic route params and searchParams, ensuring it can be rendered as a Server Component without client‑side JavaScript.
Discuss the performance implications of parsing large searchParams objects in a Server Component that renders a big table, and how you’d mitigate any overhead.
If you need to share a page component between client and server environments, how would you abstract access to params and searchParams to keep the API stable?
Your organization is migrating a monolith to Next.js 13 with Server Components. How would you establish conventions around using params vs. searchParams to avoid cross‑team bugs?
In a multi‑tenant SaaS, the tenant identifier can appear either as a path segment or a query parameter. How would you design routing and data fetching to handle both consistently while keeping Server Components pure?
What trade‑offs would you consider when deciding to expose searchParams via a custom hook versus passing them down from a layout, especially regarding type safety and bundle size?